package com.qf.gateway.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;

import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;

import java.security.spec.ECField;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//GlobalFilter  实现过滤器
//Ordered 顺序
public class GatewayFilter implements GlobalFilter, Ordered {
    /**
     * 基于webflux的filter
     * @param exchange
     * @param chain
     * @return
     */

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestUrl = exchange.getRequest().getPath().toString();
        if (requestUrl.equals("/user/signin") || requestUrl.equals("/user.signup")) {
            //既不登录也不注册，其它请求拿到请求头看看token合不合法
            List<String> tokens = exchange.getRequest().getHeaders().get("token");
            boolean checkToken = true;
            //校验token
            if (tokens != null) {
                String token = tokens.get(0);
                try {
                    Jwts.parser().setSigningKey("qianfeng".getBytes()).parseClaimsJws(token).getBody();
                } catch (Exception e) {
                    //token有问题
                    checkToken = false;
                }

            } else {
                checkToken = false;
            }
            if (!checkToken) {
                //token校验失败
                //不用转发给下游子服务
                ServerHttpResponse response = (ServerHttpResponse) exchange.getResponse();
                //基于webflux模型响应数据给前端
                return response.writeAndFlushWith(Flux.just(
                        ByteBufFlux.just(
                                response.bufferFactory().wrap(getWrapData())
                        )
                ));
            }

        }
        return chain.filter(exchange).then(
                Mono.fromRunnable(new Runnable() {
                    @Override
                    public void run() {
                        //修改响应头中的信息
                        //协议层统一解决所有跨域问题
                        //所有子服务的跨域问题
                        HttpHeaders headers = exchange.getResponse().getHeaders();
                        headers.remove("Access-Control-Allow-Credentials");
                        headers.remove("Access-Control-Allow-Origin");
                        headers.remove("Access-Control-Allow-Method");
                        headers.remove("Access-Control-Max-Age");
                        headers.remove("Access-Control-Allow-Headers");
                        headers.remove("Access-control-Expose-Headers");
                        //添加可以不导致跨域的头
                        headers.add("Access-Control-Allow-Credentials", "true");
                        headers.add("Access-Control-Allow-Origin", "*");
                        headers.add("Access-Control-Allow-Method", "GET,POST,DELETE,PUT,OPTIONS");
                        headers.add("Access-Control-Max-Age", "3600");
                        headers.add("Access-Control-Allow-Headers", "new-token,Content-Type,Accept,Origin,X-Requested-With");
                        headers.add("Access-Control-Expose-Headers", "Location");

                    }
                })
        );
    }



    @Override
    public int getOrder() {
        return 1;
    }
    private byte[]getWrapData(){
        Map<String,String> map=new HashMap<>();
        map.put("code", "401");
        map.put("msg", "请使用一个有效的token");
        map.put("result", null);
        try {
            return  new ObjectMapper().writeValueAsString(map).getBytes();
        }catch (Exception e){
            e.printStackTrace();
        }

        return "error".getBytes();
    }
}
